package com.doge.walknovel.api.security

import android.annotation.SuppressLint
import android.text.TextUtils
import android.util.Base64
import java.nio.charset.StandardCharsets
import java.security.Key
import java.security.MessageDigest
import javax.crypto.Cipher
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec

object ApiDigest {
    private const val UTF8 = "UTF-8"
    private val IV = IvParameterSpec(byteArrayOf(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
    private val HEX_ARRAY = "0123456789abcdef".toCharArray()
    private const val ALGORITHM = "AES"
    private const val TRANSFORMATION = "AES/CBC/PKCS5Padding"
    private fun getHash(algorithm: String, text: String): ByteArray {
        return try {
            getHash(algorithm, text.toByteArray(StandardCharsets.UTF_8))
        } catch (ex: Exception) {
            throw RuntimeException(ex.message)
        }
    }

    fun encrypt(str: String, key: String): String {
        return try {
            if (TextUtils.isEmpty(str)) {
                ""
            } else encrypt(str.toByteArray(StandardCharsets.UTF_8), key)
        } catch (ex: Exception) {
            throw RuntimeException(ex.message)
        }
    }

    @Throws(Exception::class)
    fun decrypt(str: String, key: String): String {
        return if (TextUtils.isEmpty(str)) {
            ""
        } else decrypt(str.toByteArray(StandardCharsets.UTF_8), key)
    }

    private fun getHash(algorithm: String, data: ByteArray): ByteArray {
        return try {
            val digest = MessageDigest.getInstance(algorithm)
            digest.update(data)
            digest.digest()
        } catch (ex: Exception) {
            throw RuntimeException(ex.message)
        }
    }

    @SuppressLint("TrulyRandom")
    private fun encrypt(data: ByteArray, key: String): String {
        return try {
            val cipher = Cipher.getInstance(TRANSFORMATION)
            val secretKey: Key = SecretKeySpec(getHash("MD5", key), ALGORITHM)
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, IV)
            val encryptData = cipher.doFinal(data)
            val base64En = Base64.encode(encryptData, Base64.NO_WRAP)
            String(base64En, StandardCharsets.UTF_8)
        } catch (ex: Exception) {
            throw RuntimeException(ex.message)
        }
    }

    @Throws(Exception::class)
    private fun decrypt(data: ByteArray, key: String): String {
        val cipher = Cipher.getInstance(TRANSFORMATION)
        val secretKey: Key = SecretKeySpec(getHash("MD5", key), ALGORITHM)
        cipher.init(Cipher.DECRYPT_MODE, secretKey, IV)
        val base64De = Base64.decode(data, Base64.NO_WRAP)
        val decryptData = cipher.doFinal(base64De)
        return String(decryptData, StandardCharsets.UTF_8)
    }
}